package chances.epg.ui.taglib.model;

import java.util.List;

public   class LinkModelRelativeCaculator {
	/**
	 * 比较二个矩形的方向上的距离
	 * 
	 * @author Coffee
	 *
	 */
	public static void caculateFocusRects(List<LinkModel> linkModels) {
		for (LinkModel aLinkModel : linkModels) {
			Rect curRect = aLinkModel.rect;
			LinkModel left = null;
			LinkModel right = null;
			LinkModel up = null;
			LinkModel down = null;

			for (LinkModel bLinkModel : linkModels) {
				Rect rectangle = bLinkModel.rect;
				// right
				if (curRect.getLeft() + curRect.getWidth() <= rectangle.getLeft()) {
					if (right == null || isXShorter(curRect, right.rect, rectangle)) {
						right = bLinkModel;
					}
				}

				// left
				if (curRect.getLeft() >= rectangle.getLeft() + rectangle.getWidth()) {
					if (left == null || isXShorter(curRect, left.rect, rectangle)) {
						left = bLinkModel;
					}
				}

				// down
				if (curRect.getTop() + curRect.getHeight() <= rectangle.getTop()) {
					if (down == null || isYShorter(curRect, down.rect, rectangle)) {
						down = bLinkModel;
					}
				}

				// up
				if (curRect.getTop() >= rectangle.getTop() + rectangle.getHeight()) {
					if (up == null || isYShorter(curRect, up.rect, rectangle)) {
						up = bLinkModel;
					}
				}
			}

			if (left != null) {
				aLinkModel.direction.leftId = left.getId();
			}

			if (right != null) {
				aLinkModel.direction.rightId = right.getId();

			}

			if (up != null) {
				aLinkModel.direction.upId = up.getId();
			}

			if (down != null) {
				aLinkModel.direction.downId = down.getId();
			}
		}
	}

	/**
	 * 比较两个位置，相对source矩形水平距离比较近.
	 * 
	 * @param source
	 * @param rec1
	 * @param rect2
	 * @return
	 */
	private static boolean isXShorter(Rect source, Rect rect1, Rect rect2) {
		boolean rect1Include = isXDirecInclude(source, rect1);
		boolean rect2Include = isXDirecInclude(source, rect2);

		if (rect1Include && !rect2Include) {
			return false;
		} else if (!rect1Include && rect2Include) {
			return true;
		} else {
			double dis1 = caculateDistance(source, rect1);
			double dis2 = caculateDistance(source, rect2);
			return dis1 >= dis2;
		}
	}

	/**
	 * 比较两个位置，相对source矩形垂直距离比较近.
	 * 
	 * @param source
	 * @param rec1
	 * @param rect2
	 * @return
	 */
	private static boolean isYShorter(Rect source, Rect rect1, Rect rect2) {
		boolean rect1Include = isXDirecInclude(source, rect1);
		boolean rect2Include = isXDirecInclude(source, rect2);

		if (rect2Include && !rect2Include) {
			return false;
		} else if (!rect1Include && rect2Include) {
			return true;
		} else {
			double dis1 = caculateDistance(source, rect1);
			double dis2 = caculateDistance(source, rect2);
			return dis1 >= dis2;
		}
	}

	/**
	 * x方向(水平方向)本矩形是否包括给定矩形aRec 包括三种情况：1，完全包括， 2,完全被包括， 3，交叉包括
	 * 
	 * @param aRec
	 * @return
	 */
	public static boolean isXDirecInclude(Rect self, Rect aRec) {
		if (self.top >= aRec.top && self.top + self.height <= aRec.top + aRec.height)
			return true;// 上述2
		if (self.top <= aRec.top && self.top + self.height >= aRec.top + aRec.height)
			return true;// 上述1
		if (self.top > aRec.top && aRec.top + aRec.height - self.top > 0)
			return true; // 上述3下部交叉 this.height/3
		if (self.top < aRec.top && self.top + self.height - aRec.top > 0)
			return true; // 上述3上部交叉
		return false;
	}

	/**
	 * y方向(垂直方向)本矩形是否包括给定矩形aRec 包括三种情况：1，完全包括， 2,完全被包括， 3，交叉包括
	 * 
	 * @param aRec
	 * @return
	 */
	public static boolean isYDirecInclude(Rect self, Rect aRec) {
		if (self.left <= aRec.left && self.left + self.width >= aRec.left + aRec.width)
			return true;// 完全包含
		if (self.left >= aRec.left && self.left + self.width <= aRec.left + aRec.width)
			return true;// 完全被包含
		if (self.left > aRec.left && aRec.left + aRec.width - self.left > 0)
			return true; // 左半部突出超过1/3 改为0 this.width/3
		if (self.left < aRec.left && self.left + self.width - aRec.left > 0)
			return true; // 右半部突出超过1/3
		return false;
	}

	/**
	 * 计算两个矩形间的距离.
	 * 
	 * @param aRec
	 * @return
	 */
	public static double caculateDistance(Rect self, Rect aRec) {
		int distanceX = Math.abs(self.left + self.width / 2 - (aRec.left + aRec.width / 2));
		int distanceY = Math.abs(self.top + self.height / 2 - (aRec.top + aRec.height / 2));
		return Math.sqrt(distanceX * distanceX + distanceY * distanceY);
	}

}
